import numpy as np
import pandas as pd
import tensorflow as tf
import keras
from keras.models import Sequential,Model
from keras.layers import Conv2D,Dense,MaxPooling2D,Flatten,GlobalAveragePooling2D,GlobalMaxPooling2D,Dropout,RandomFlip,RandomRotation,Activation
from keras.applications.vgg16 import VGG16
import cv2
import matplotlib.pyplot as plt
%matplotlib inline
import imghdr
import os
import plotly.express as px
import plotly.offline as pyo
pyo.init_notebook_mode()
The below function checks the images in the data folder and removes images with extension other than jpg,jpeg and png
directory='data'
for cls in os.listdir(directory):
for path in os.listdir(os.path.join(directory,cls)):
img_path=os.path.join(directory,cls,path)
img=cv2.imread(img_path)
filetype=imghdr.what(img_path)
if filetype not in ['jpg','jpeg','png']:
os.remove(img_path)
image_dataset_from_directory function collects images from the folder, resizes the images of shape 256 x 256, creates batches and shuffles images. This function also takes care of creating labels for the images.
data=tf.keras.preprocessing.image_dataset_from_directory('data',batch_size=16)
The above function returns a generator and we will convert it into a numpy iterator for iterating over batches
data_iterator=data.as_numpy_iterator()
## Returns a batch from the iterator
batch=data_iterator.next()
The iterator returns a tuple of 16(batch_size) images and their corresponding labels.
len(batch)
batch[0].shape
batch[1]
fig,ax=plt.subplots(nrows=1,ncols=3,figsize=(15,15))
for i,img in enumerate(batch[0][:3]):
ax[i].imshow(img.astype('int'))
ax[i].title.set_text(batch[1][i])
ax[i].axis('off')
From the images above we can infer the labels of the image as:
Male - 0
Female - 1</b>
In preprocessing we will clip our data to a range of 0-1 instead of 0-255. This helps our deepl learning model to generalize quickly.
data=tf.keras.preprocessing.image_dataset_from_directory('data',batch_size=16)
data=data.map(lambda x,y:(x/255,y)) ## This function clips pixels in the range of 0-1
data_iterator=data.as_numpy_iterator()
batch=data_iterator.next()
fig,ax=plt.subplots(nrows=1,ncols=3,figsize=(15,15))
for i,img in enumerate(batch[0][:3]):
ax[i].imshow(img)
ax[i].title.set_text(batch[1][i])
ax[i].axis('off')
Here we take 70% of data for training, 20% for validation and 10% for testing
train_size=int(len(data)*0.7)
val_size=int(len(data)*0.2)+1
test_size=int(len(data)*0.1)
train_set=data.take(train_size)
val_set=data.skip(train_size).take(val_size)
test_set=data.skip(train_size+val_size).take(test_size)
model=Sequential()
model.add(Conv2D(filters=32,kernel_size=(3,3),activation='relu',input_shape=(256,256,3)))
model.add(MaxPooling2D())
model.add(Conv2D(filters=64,kernel_size=(3,3),activation='relu'))
model.add(MaxPooling2D())
model.add(Conv2D(filters=128,kernel_size=(3,3),activation='relu'))
model.add(MaxPooling2D())
# model.add(Conv2D(filters=256,kernel_size=(3,3),activation='relu'))
# model.add(MaxPooling2D())
model.add(Flatten())
#model.add(Dense(256,activation='relu'))
model.add(Dense(64,activation='relu'))
model.add(Dense(1,activation='sigmoid'))
model.summary()
model.compile(loss='binary_crossentropy',metrics=['accuracy'],optimizer='adam')
callbacks_reduced_params=[
keras.callbacks.ModelCheckpoint(filepath='model_reduced_parameters_bestweights2.h5',save_best_only=True),
keras.callbacks.ReduceLROnPlateau(monitor='val_accuracy',mode=max,factor=0.05,patience=3)
]
history_reduced_params=model.fit(train_set,epochs=5,validation_data=val_set,callbacks=[callbacks_reduced_params])
historyReducedParamsDF=pd.DataFrame(history_reduced_params.history)
fig=px.line(historyReducedParamsDF,y=historyReducedParamsDF.columns[1:4:2],title='Training accuracy vs Validation accuracy')
fig.update_layout(xaxis=dict(title='epochs'),
yaxis=dict(title='Loss'))
fig=px.line(historyReducedParamsDF,y=historyReducedParamsDF.columns[0:3:2],title='Training loss vs Validation loss')
fig.update_layout(xaxis=dict(title='epochs'),
yaxis=dict(title='Loss'))
from keras.metrics import Precision,Recall,BinaryAccuracy
precision=Precision()
recall=Recall()
accuracy=BinaryAccuracy()
for x,y in test_set.as_numpy_iterator():
yhat=model.predict(x)
precision.update_state(y,yhat)
recall.update_state(y,yhat)
accuracy.update_state(y,yhat)
print(f'Precision: {precision.result().numpy()}, Recall: {recall.result().numpy()}, Accuracy: {accuracy.result().numpy()}')
yhat=0
def predict(img_path):
img=cv2.imread(img_path)
resized_image=cv2.resize(img,dim=(256,256))
rescaled_image=resized_image/255.0
yhat=model.predict(np.expand_dims(rescaled_image,0))
label=''
print(yhat.flatten()[0])
if yhat<0.5:
label='Male'
else:
label='Female'
plt.imshow(rescaled_image)
plt.axis('off')
plt.title(label)
predict('45-455687_south-indian-teen-girls.jpg')